#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>

#define BUFFER_SIZE 512

void changeLengthField(char*);
int* decimalToOctal(int);
void readLength(char*);

int main(int argc, char** argv)
{
	if(argc != 2)
	{
		printf("Usage: ./[exe] [tar_file_path]\n");
		return -1;
	}

	changeLengthField(argv[1]);

	readLength(argv[1]);

	return 0;
}

void readLength(char* filepath)
{
	int fd = 0;
	if ((fd = open(filepath, O_RDONLY)) < 0)
	{
		printf("Couldn't open tar file to read\n");
		return;
	}

	char buffer[BUFFER_SIZE];
	char *bp;   
	int bufferChars;
	while(1)
	{
		if ((bufferChars = read(fd, buffer, BUFFER_SIZE)) > 0)
		{
			bp = buffer;
			if(bp != NULL)
				printf("File Contents:\n%s\n \n",bp);

			int sizeOfFile = octalStringToInt(&buffer[124], 11);
			if(sizeOfFile == 1227133520)
			{
				break; //do this for formatting...for now...
			}
			
			if (buffer[156] == '0' || buffer[156]=='\0')
			{
				printf("Size : %d\n",sizeOfFile);
			}
		}
		else if(bufferChars == 0)
		{
			break;
		}
		else
		{
			printf("Read failed\n");
			break;
		}
	}
}

void changeLengthField(char* filepath)
{
	int fd;
	char buffer[BUFFER_SIZE];
	int bufferChars = 0;

	//read in header
	if((fd = open(filepath, O_RDWR)) == -1)
	{
		fprintf(stderr, "Could not open file %s\n", filepath);
		return;
	}
	if ((bufferChars = read(fd, buffer, BUFFER_SIZE)) < 0)
	{
		printf("Read failed");
		return;
	}
	close(fd); //close file

	int length = octalStringToInt(&buffer[124], 11);
	printf("old length: %d\n", length);

	int newsize = calculateHeaderOffset(length);

	newsize = newsize + 148 + 4; //point into middle of header checksum

	printf("new length: %d\n", newsize);

	int* nums = decimalToOctal(newsize);

	int i, j;
/*
	for(i = 0; i < sizeof(nums); i++)
	{
		printf("%d", nums[i]);
	}
	printf("\n");
*/
	//augment header
	for(i = 0, j = 134; i < sizeof(nums); i++, j--)
	{
		char character = (char)nums[i] + '0';
		buffer[j] = character;
	}

	//write new header
	if((fd = open(filepath, O_RDWR)) == -1)
	{
		fprintf(stderr, "Could not open file %s\n", filepath);
		return;
	}
	write(fd, buffer, BUFFER_SIZE);
	close(fd);
	free(nums);
}


int calculateHeaderOffset(int sizeOfFile)
{
	int remainder = sizeOfFile % 512;
	int filePadding = 512 - remainder;
	//length of file + padding to get to 512 divisible byte count + checksum offset + half the checksum field size (8/2 = 4)
	int nextHeaderChecksumOffset = sizeOfFile + filePadding + 512;

	return nextHeaderChecksumOffset;
}

int* decimalToOctal(int num)
{
	int cnt = 0;
	int* nums = (int*)malloc(sizeof(int)*100);
	while (num != 0)
	{
		/* we save all reminders in the array */
		nums[cnt++] = num % 8;
		num = num / 8;
	}
	return nums;
}

int arrToInt(int nums[], int count)
{
	int tmp = 0;
	for(count = count - 1; count >= 0; count--)
	{
		tmp += nums[count]*power(10, count);
	}

	return tmp;
}

int power(int base, int exponent)
{
	int i;
	int result = 1;
	for(i = 1; i <= exponent; i++)
	{
		result = result * base;
	}

	return result;
}

int octalStringToInt(char *string, unsigned int size){
  unsigned int output = 0;
  while(size > 0){
    output = output*8 + *string - '0';
    string++;
    size--;
  }
  return output;
}

